<html>
  <head>
    <title>领域服务  公约与最佳实践</title>
  </head>
  <body>
    <script>
      // 领域服务  公约与最佳实践

            /*
                一、领域服务

                        1、在领域层中定义领域服务

                        2、不要为领域服务创建接口，除非你有充分的理由（例如模拟和测试不同的实现）。

                        3、使用Manager后缀为你的领域服务命名。

                      
                        eg:
                              public class IssueManager : DomainService
                              {
                                //...
                              }

            */

            /*
                二、领域服务方法

                      1、不要定义GET方法。GET方法不会改变实体的状态。

                            当你做get操作是，请直接在应用服务层中使用存储库，而不是使用领域服务。

                      2、领域服务的方法只是用来修改实体，更改实体或聚合根的状态，或者实现实体变更的逻辑。

                      3、不要使用太过泛的名称来命名方法  (如，UpdateIssueAsync就不是很好)

                      4、定义具有实现特定域逻辑的不言自明名称（如AssignToAsync）的方法。

                      5、接受有效的"领域对象"作为参数。

                            eg:
                                  public async Task AssignToAsync(Issue issue, IdentityUser user)
                                  {
                                      //...
                                  }

                      6、如果验证失败，请抛出BusinessException或自定义业务异常。

                                用具有唯一代码命名空间的域错误代码进行异常本地化。

                                eg：   
                                        public async Task AssignToAsync(Issue issue, IdentityUser user)
                                        {
                                            var openIssueCount = await _issueRepository.GetCountAsync(
                                                    i => i.AssignedUserId == user.Id && !i.IsClosed
                                                );

                                                if (openIssueCount >= 3)
                                                {
                                                    throw new BusinessException("IssueTracking:ConcurrentOpenIssueLimit");
                                                }

                                                issue.AssignedUserId = user.Id;
                                        }

                        7、不要返回DTO。只在需要时返回领域对象


                        8、不应该涉及用户验证逻辑。需要时，定义额外的参数来从应用服务层接收 CurrentUser的相关数据。
            */
    </script>
  </body>
</html>